package com.lyy.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lyy.common.constant.Token;
import com.lyy.common.shiro.JWTUtil;
import com.lyy.common.sms.ALiYunSMSModel;
import com.lyy.common.sms.SendSMS;
import com.lyy.common.utils.Constants;
import com.lyy.common.utils.DateUtils;
import com.lyy.common.utils.UUIDUtils;
import com.lyy.system.dao.SysVcodeDao;
import com.lyy.system.dao.SysVcodeLogDao;
import com.lyy.system.dao.SysWhitePhoneDao;
import com.lyy.system.pojo.SysVcode;
import com.lyy.system.pojo.SysVcodeLog;
import com.lyy.common.sms.ALiYunSMSModel.SMS_TYPE;
import com.lyy.common.sms.ALiYunSMSModel.TEMPLATE_TYPE;
import com.lyy.system.pojo.SysWhitePhone;
import com.lyy.system.service.SysVcodeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 发送消息记录最新一条(SysVcode)表服务实现类
 *
 * @author Yw
 * @since 2021-02-02 17:48:37
 */
@Slf4j
@Service
public class SysVcodeServiceImpl extends ServiceImpl<SysVcodeDao, SysVcode> implements SysVcodeService {

    @Resource
    private SysVcodeLogDao sysVcodeLogDao;

    @Resource
    private SysWhitePhoneDao sysWhitePhoneDao;
    @Autowired
    @Qualifier(value = "ALiYunSMSUtils")
    private SendSMS sendSMS;

    /**
     * 添加发送消息记录最新一条
     *
     * @param sysVcode
     */
    @Override
    public void createSysVcode(SysVcode sysVcode) {
        baseMapper.insert(sysVcode);
    }

    /**
     * 根据主键修改发送消息记录最新一条
     *
     * @param sysVcode
     */
    @Override
    public void updateSysVcode(SysVcode sysVcode) {
        baseMapper.update(sysVcode, new UpdateWrapper<SysVcode>()
                .eq("username", sysVcode.getUsername())
        );
    }

    /**
     * 根据主键删除发送消息记录最新一条
     *
     * @param username 手机号码
     * @return
     */
    @Override
    public void deleteSysVcode(SysVcode sysVcode) {
        baseMapper.delete(new UpdateWrapper<SysVcode>()
                .eq("username", sysVcode.getUsername())
        );
    }

    /**
     * 根据主键查询发送消息记录最新一条详情
     *
     * @param username 手机号码
     * @return
     */
    @Override
    public SysVcode getSysVcode(SysVcode sysVcode) {
        return baseMapper.selectOne(new QueryWrapper<SysVcode>()
                .eq("username", sysVcode.getUsername())
        );
    }

    /**
     * 批量添加发送消息记录最新一条
     *
     * @param sysVcodes
     */
    @Override
    public int batchInsert(List<SysVcode> sysVcodes) {
        return baseMapper.batchInsert(sysVcodes);
    }


    /**
     * 批量修改发送消息记录最新一条
     *
     * @param sysVcodes
     */
    @Override
    public int batchUpdate(List<SysVcode> sysVcodes) {
        return baseMapper.batchUpdate(sysVcodes);
    }

    /**
     * 查询发送消息记录最新一条列表
     *
     * @param sysVcode
     */
    @Override
    public List<SysVcode> selectSysVcodeList(SysVcode sysVcode) {
        return baseMapper.selectSysVcodeList(sysVcode);
    }

    /**
     * 查询发送消息记录最新一条数量
     *
     * @param sysVcode
     */
    @Override
    public int selectSysVcodeCount(SysVcode sysVcode) {
        return baseMapper.selectSysVcodeCount(sysVcode);
    }

    @Override
    public Token getToken(String username) {
        String key = JWTUtil.sign(username);
        return new Token(key, org.apache.commons.lang3.time.DateUtils.addSeconds(new Date(), (int) Constants.EXPIRE_TIME / 1000));
    }

    /**
     * 导入发送消息记录最新一条excel
     *
     * @param sysVcodes
     */
    @Override
    public List<Map<String, String>> importSysVcodeExcel(List<SysVcode> sysVcodes) {
        List<Map<String, String>> mapList = new ArrayList<>();
        sysVcodes.forEach(sysVcode -> {
            sysVcode.setUsername(UUIDUtils.getUUIDTWO());
            Map<String, String> map = new HashMap<>();
            map.put("status", "0");
            map.put("reason", "导入成功");
            mapList.add(map);
        });
        batchInsert(sysVcodes);
        return mapList;
    }

    @Override
    public int checkWhitePhone(String username) {
        return sysWhitePhoneDao.selectCount(new QueryWrapper<SysWhitePhone>().eq("phone", username).eq("del_flag", "0"));
    }

    @Override
    public String getPhoneCode(String username) {
        String scode = createSmsCode();
        SysVcode vcode = baseMapper.selectById(username);
        long currentTime = System.currentTimeMillis();
        SysVcodeLog vcodeLog = new SysVcodeLog();
        if (null != vcode) {
            long timeStamp1 = Long.parseLong(vcode.getTimeStamp1());// 每天开始一次的时间戳
            long timeStamp2 = Long.parseLong(vcode.getTimeStamp2());// 上一次时间戳
            int count1 = vcode.getAcount1();// 每天记录数
            int count2 = vcode.getAcount2();// 每小时记录数
            long firstTimeStamp = DateUtils.getDayBegin(new Date()).getTime();
            // 判断每次时间间隔不能小于3分钟
            if (currentTime - timeStamp1 < Constants.TIME_DIFF) {
                log.info("每次时间间隔不能小于3分钟！");
                return "3";
            }
            // 判断每小时不能超过5次
            if (count2 > 5) {
                if (currentTime - timeStamp2 < Constants.HOUR_DIFF) {
                    log.info("每小时获取动态验证码不能超过5次！");
                    return "5";
                } else {
                    timeStamp2 = currentTime;
                    count2 = 1;
                }
            } else {
                count2++;
            }
            // 判断每天不能超过20次
            if (count1 > 20) {
                if (timeStamp1 < firstTimeStamp) {
                    count1 = 1;
                } else if (currentTime > timeStamp1) {
                    log.info("每天获取动态验证码不能超过20次！");
                    return "20";
                }
            } else {
                count1++;
            }
            vcode.setVcode(scode);
            vcode.setTimeStamp1(String.valueOf(currentTime));
            vcode.setAcount1(count1);
            vcode.setTimeStamp2(String.valueOf(timeStamp2));
            vcode.setAcount2(count2);
            baseMapper.updateById(vcode);
        } else {
            vcode = new SysVcode();
            vcode.setUsername(username);
            vcode.setVcode(scode);
            vcode.setTimeStamp1(String.valueOf(currentTime));
            vcode.setAcount1(1);
            vcode.setTimeStamp2(String.valueOf(currentTime));
            vcode.setAcount2(1);
            baseMapper.insert(vcode);
        }
        vcodeLog.setUsername(username);
        vcodeLog.setVcode(scode);
        vcodeLog.setCreateDate(new Date());
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("PhoneNumbers", username);
        paramMap.put("SignName", ALiYunSMSModel.SignName);
        paramMap.put("TemplateCode", ALiYunSMSModel.getTemplateString(TEMPLATE_TYPE.SEND_CODE));
        Map<String, Object> map = new HashMap<>();
        map.put("code", scode);
        paramMap.put("TemplateParam", ALiYunSMSModel.getModelString(SMS_TYPE.SEND_CODE, map));
        boolean returnCode = sendSMS.sendSMS(paramMap);
        if (returnCode) {
            sysVcodeLogDao.insert(vcodeLog);
            return scode;
        } else {
            log.info("手机验证码发送失败！手机号：" + username);
            return "0";
        }
    }

    private static final char[] CODE_SEQUENCE = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};

    /**
     * 生成动态验证码
     */
    public String createSmsCode() {
        StringBuilder randomCode = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < Constants.CODE_BIT; i++) {
            String strRand = String.valueOf(CODE_SEQUENCE[random.nextInt(CODE_SEQUENCE.length)]);
            randomCode.append(strRand);
        }
        return randomCode.toString();
    }

    @Override
    public SysVcode getVcodeById(String username) {
        return baseMapper.selectById(username);
    }
}